package com.project.web.config.WxCorp;

import com.google.common.collect.Maps;
import com.project.web.util.handler.*;
import com.project.web.wechat.model.app.WxBizAppConfig;
import com.project.web.wechat.model.app.WxBizConfig;
import com.project.web.wechat.service.app.WxBizConfigService;
import lombok.val;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author WYY
 */
@Configuration
public class WxCpConfiguration {
    private LogHandler logHandler;
    private NullHandler nullHandler;
    private LocationHandler locationHandler;
    private MenuHandler menuHandler;
    private MsgHandler msgHandler;
    private UnsubscribeHandler unsubscribeHandler;
    private SubscribeHandler subscribeHandler;
    private static Map<String, Map<String, WxCpMessageRouter>> wxCpMessageRouters = Maps.newHashMap();
    private static Map<String, Map<String, WxCpService>> wxCpServices = Maps.newHashMap();

    @Resource(name = "wxBizConfigServiceImpl")
    private WxBizConfigService wxBizConfigService;

    @Autowired
    public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler,
                             MenuHandler menuHandler, MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler,
                             SubscribeHandler subscribeHandler) {
        this.logHandler = logHandler;
        this.nullHandler = nullHandler;
        this.locationHandler = locationHandler;
        this.menuHandler = menuHandler;
        this.msgHandler = msgHandler;
        this.unsubscribeHandler = unsubscribeHandler;
        this.subscribeHandler = subscribeHandler;
    }

    @PostConstruct
    public void initServices() {
        List<WxBizConfig> wxBizConfigs = wxBizConfigService.selectListOfApps();
        for (WxBizConfig Config : wxBizConfigs) {
            List<WxBizAppConfig> AppConfigs = Config.getWxBizAppConfigs();
            Map<String, WxCpService> wxCpServiceMap = new HashMap<>();
            Map<String, WxCpMessageRouter> wxCpMessageRouterMap = new HashMap<>();
            for (WxBizAppConfig appConfig : AppConfigs) {
                WxCpDefaultConfigImpl configStorage = new WxCpDefaultConfigImpl();

                configStorage.setCorpId(Config.getCorpid());
                configStorage.setAgentId(Integer.valueOf(appConfig.getAgentId()));
                configStorage.setCorpSecret(appConfig.getAgentSecret());
                configStorage.setToken(appConfig.getServerToken());
                configStorage.setAesKey(appConfig.getServerKey());
                WxCpService service = new WxCpServiceImpl();
                service.setWxCpConfigStorage(configStorage);
                wxCpServiceMap.put(appConfig.getAgentId(), service);
                wxCpMessageRouterMap.put(appConfig.getAgentId(), newRouter(service));
            }
            wxCpServices.put(Config.getCorpid(), wxCpServiceMap);
            wxCpMessageRouters.put(Config.getCorpid(), wxCpMessageRouterMap);
        }
    }

    /**
     * 根据企业ID、应用ID查询wxCpService
     *
     * @param corpId  企业ID
     * @param agentId 应用ID
     * @return
     */
    public static WxCpService getCpService(String corpId, String agentId) {
        return wxCpServices.get(corpId).get(agentId);
    }

    /**
     * 根据企业ID、应用ID查询消息路由
     *
     * @param corpId  企业ID
     * @param agentId 应用ID
     * @return
     */
    public static WxCpMessageRouter getCpMsgRouter(String corpId, String agentId) {
        return wxCpMessageRouters.get(corpId).get(agentId);
    }

    /**
     * 初始化消息路由
     *
     * @param wxCpService 企业微信service
     * @return
     */
    private WxCpMessageRouter newRouter(WxCpService wxCpService) {
        final val newRouter = new WxCpMessageRouter(wxCpService);

        // 记录所有事件的日志 （异步执行）
        newRouter.rule().handler(this.logHandler).next();

        // 自定义菜单事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end();

        // 点击菜单链接事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();

        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler)
                .end();

        // 取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.UNSUBSCRIBE)
                .handler(this.unsubscribeHandler).end();

        // 上报地理位置事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.LOCATION).handler(this.locationHandler)
                .end();

        // 接收地理位置消息
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
                .handler(this.locationHandler).end();

        // 扫码事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SCAN).handler(this.nullHandler).end();

        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end();

        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT).handler(new ExternalContactChangeHandler()).end();

        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end();

        // 默认
        newRouter.rule().async(false).handler(this.msgHandler).end();

        return newRouter;
    }
}
